【コマンドライン】標準入出力とリダイレクト・パイプ

【コマンドライン】標準入出力とリダイレクト・パイプ

コマンドラインの標準入出力、リダイレクト、パイプについて解説します。

検証環境

標準入出力

標準入出力は“標準の入力と出力のこと”です。

主に『標準入力』・『標準出力』・『標準エラー出力』の3種類があります。

『コマンドラインへの入力』や『プログラムの実行結果の出力』などは標準入出力を通して行われます。

そして、これらの入出力にはファイルディスクリプタ(FD)と呼ばれる値が振り分けられています。

入出力 FD値
標準入力 0
標準出力 1
標準エラー出力 2

ファイルディスクリプタ

ファイルディスクリプタ(FD)はOSがファイルを識別するために振り分ける値です。

ファイルと言うと少し理解しづらいですが、『どこのデータかを識別する値』というイメージです。

例えば、『0はキーボードの入力データ』や『1はディスプレイへの出力データ』などです。

入出力 FD値 初期対象
標準入力 0 キーボード
標準出力 1 ディスプレイ
標準エラー出力 2 ディスプレイ

リダイレクト

リダイレクトは“入力元や出力先を変更すること”です。

標準入力や標準出力、エラー出力を変更するには特定の記号やFD値を使用します。

標準入力

入力元を変更するには<を使います。

例えば、catコマンドにsampleファイルをリダイレクトで入力する場合は次のようになります。

___ih_hl_start
$ cat < sample
___ih_hl_end
#!/bin/sh
echo "Hello World"

一見、リダイレクトを使用しない$ cat sampleと同じに見えますが、内部的には異なる処理です。

リダイレクトを使用しない場合、『ファイルを読み込む』という処理がありますが、リダイレクトを使用した場合はsampleファイルの内容(テキスト)をcatコマンドに渡すため、その処理がありません。

標準出力

出力先を変更するには>とFD値を使います。

例えば、lsコマンドは実行すると標準出力(コマンドラインの画面)に結果を書き出します。

$ ls -l
-rw-rw-r-- 1 hacker staff 29  8月 20 16:53 sample
-rw-rw-r-- 1 hacker staff  0  8月 20 16:56 test

この出力先を>と標準出力のFD値(1)を使い、result.txtファイルに変更します。

___ih_hl_start
$ ls -l 1> result.txt
___ih_hl_end
$ cat result.txt 
-rw-rw-r-- 1 hacker staff  0  8月 20 16:59 result.txt
-rw-rw-r-- 1 hacker staff 29  8月 20 16:53 sample
-rw-rw-r-- 1 hacker staff  0  8月 20 16:56 test

1行目の1>がリダイレクトです。

lsコマンド実行時にコマンドラインへ出力されなくなり、代わりにresult.txtに出力(書き込み)されました。

なお、>は書き込み先の内容を上書きするため、元の内容は消えます。

元の内容を残したまま追記するには、>>を使用します。

___ih_hl_start
$ ls -l 1>> result.txt
___ih_hl_end
$ cat result.txt 
-rw-rw-r-- 1 hacker staff  0  8月 20 16:59 result.txt
-rw-rw-r-- 1 hacker staff 29  8月 20 16:53 sample
-rw-rw-r-- 1 hacker staff  0  8月 20 16:56 test
-rw-rw-r-- 1 hacker staff 179  8月 20 16:59 result.txt
-rw-rw-r-- 1 hacker staff  29  8月 20 16:53 sample
-rw-rw-r-- 1 hacker staff   0  8月 20 16:56 test

また、標準出力のリダイレクトはFD値を省略できます。

___ih_hl_start
$ ls -l > result.txt
___ih_hl_end
$ cat result.txt 
-rw-rw-r-- 1 hacker staff  0  8月 20 16:59 result.txt
-rw-rw-r-- 1 hacker staff 29  8月 20 16:53 sample
-rw-rw-r-- 1 hacker staff  0  8月 20 16:56 test

エラー出力

エラー出力先のリダイレクトは基本的に標準出力と同様ですが、FD値を2にします。

___ih_hl_start
$ ls -l tmp 2> result.txt 
___ih_hl_end
$ cat result.txt 
ls: tmp にアクセスできません: そのようなファイルやディレクトリはありません

リダイレクトのパターン

頻繁に使用するリダイレクトのパターンをご紹介します。

コマンド < ファイル

コマンドにファイルの内容を入力します。

___ih_hl_start
$ cat < sample 
___ih_hl_end
#!/bin/sh
echo "Hello World"

コマンド << 終了文字

終了文字が入力されるまで、キーボードから入力します。

___ih_hl_start
$ cat << "EOF"
___ih_hl_end
> Hello
> World
> EOF
Hello
World

コマンド > ファイル

コマンドの標準出力でファイルを上書きします。

$ cat memo.txt 
Hello World!
___ih_hl_start
$ cat memo.txt > result.txt
___ih_hl_end
$ cat result.txt 
Hello World!

コマンド >> ファイル

コマンドの標準出力をファイルに追記します。

$ cat memo.txt
Hello World!
___ih_hl_start
$ cat memo.txt >> result.txt
$ cat memo.txt >> result.txt
___ih_hl_end
$ cat result.txt 
Hello World!
Hello World!

コマンド 2> ファイル

コマンドのエラー出力でファイルを上書きします。

$ cat sample.txt
cat: sample.txt: そのようなファイルやディレクトリはありません
___ih_hl_start
$ cat sample.txt 2> result.txt
___ih_hl_end
$ cat result.txt 
cat: sample.txt: そのようなファイルやディレクトリはありません

コマンド 2>> ファイル

コマンドのエラー出力をファイルに追記します。

$ cat sample.txt
cat: sample.txt: そのようなファイルやディレクトリはありません
___ih_hl_start
$ cat sample.txt 2>> result.txt
$ cat sample.txt 2>> result.txt
___ih_hl_end
$ cat result.txt 
cat: sample.txt: そのようなファイルやディレクトリはありません
cat: sample.txt: そのようなファイルやディレクトリはありません

コマンド > ファイル 2>&1

コマンドの標準出力とエラー出力でファイルを上書きします。

$ ls sample tmp
ls: tmp にアクセスできません: そのようなファイルやディレクトリはありません
sample:
memo.txt
___ih_hl_start
$ ls sample tmp > result.txt 2>&1
___ih_hl_end
$ cat result.txt 
ls: tmp にアクセスできません: そのようなファイルやディレクトリはありません
sample:
memo.txt

コマンド >> ファイル 2>&1

コマンドの標準出力とエラー出力をファイルに追記します。

$ ls sample tmp
ls: tmp にアクセスできません: そのようなファイルやディレクトリはありません
sample:
memo.txt
___ih_hl_start
$ ls sample tmp >> result.txt 2>&1
$ ls sample tmp >> result.txt 2>&1
___ih_hl_end
$ cat result.txt 
ls: tmp にアクセスできません: そのようなファイルやディレクトリはありません
sample:
memo.txt
ls: tmp にアクセスできません: そのようなファイルやディレクトリはありません
sample:
memo.txt

コマンド > /dev/null 2>&1

コマンドの標準出力とエラー出力を破棄します。(表示しない)

$ ls sample tmp
ls: tmp にアクセスできません: そのようなファイルやディレクトリはありません
sample:
memo.txt
___ih_hl_start
$ ls sample tmp > /dev/null 2>&1
___ih_hl_end
$ 

パイプ

パイプはコマンドの標準出力を次のコマンドに入力する方法です。

書式は次のようになり、コマンドとコマンドの間に|を入力します。

$ コマンド | コマンド

例えば、lsコマンドの標準出力をgrepコマンドに渡すには次のようになります。

※ grepコマンドは引数で与えた文字がマッチする部分を絞り込むコマンドです。

$ ls
memo.txt  result.txt  sample  sample_test.txt  test
___ih_hl_start
$ ls | grep sample
___ih_hl_end
sample
sample_test.txt
$